<?php
class Delivery_Model_PedidoCreator
{
    const MINUTES = 15;
	public static $error;
    
	/**
	 * @param Delivery_Model_Negocio $negocio
	 * @param Delivery_Model_Cliente $cliente
	 * @param Delivery_Model_ClienteDireccion $direccion
	 * @param array $productos
	 * @param array $promociones
	 * @param string $notasCliente
	 */
	
	public function hacer( 	$tipo, $idNegocio, $idCliente, $idDireccionCliente, 
							$productosP, $promocionesP, $notasCliente, $pagaCon, $fechaEntrega )
	{
		
		$db = Zend_Registry::get('db');								
		$db->beginTransaction();

		$mapperN = Delivery_Model_Factory::mapper( 'Negocios' );
		$mapperC = Delivery_Model_Factory::mapper( 'Clientes' );
		$mapperD = Delivery_Model_Factory::mapper( 'DireccionesCliente' );
		$mapperZ = Delivery_Model_Factory::mapper( 'Zonas' );
		$mapperP = Delivery_Model_Factory::mapper( 'Productos' );
		$mapperP2= Delivery_Model_Factory::mapper( 'Pedidos' );
		
		$negocio = $mapperN->getById( $idNegocio );
		$mapperN->loadHorarios( $negocio );
		$cliente = $mapperC->getById( $idCliente );
		
		try {
		
			if ( ! $negocio->estaAbierto() ){
				throw new Delivery_Model_Exception( Delivery_Model_Exception::ORDER_CREATION_CLOSE);	
			}
			
		    if ( !count($productosP) && !count($promocionesP) ){
				throw new Delivery_Model_Exception( Delivery_Model_Exception::ORDER_CREATION_EMPTY);	
			}
		    
		    
			if ( $tipo == 'delivery' && ! $negocio->delivery){
				throw new Delivery_Model_Exception( Delivery_Model_Exception::ORDER_CREATION_DELIVERY);	
			}
			
			if ( $tipo == 'pickup' && ! $negocio->pickup){
				throw new Delivery_Model_Exception( Delivery_Model_Exception::ORDER_CREATION_PICKUP);	
			}
			
			
			if ( ! $negocio->programado && ! $negocio->estaOnline() ){
				throw new Delivery_Model_Exception( Delivery_Model_Exception::ORDER_CREATION_OFFLINE);	
			} 
			elseif( ! $this->_isValidTime( $negocio->horariosWeek( $tipo ), $fechaEntrega)) {
			
			    throw new Delivery_Model_Exception( Delivery_Model_Exception::ORDER_CREATION_TIME );
			}
			
			if ( $tipo == 'delivery' ){
				
				$direccion = $mapperD->getById( $idDireccionCliente );
				
				try {
					$zona = $mapperZ->getByDireccion( $negocio->idNegocio, $direccion->idDireccionCliente);
				} catch (Delivery_Model_Exception $e) {
					throw new Delivery_Model_Exception( Delivery_Model_Exception::ORDER_CREATION_ZONE );
				}	
			
				$total = $zona->precio;
			} else {
				$total = 0;
			}
			
			$stoks = array();
			
			foreach ($productosP as $producto){				
			
				if ( $producto->cantidadDisponible < $producto->cantidad){
//					throw new Delivery_Model_Exception('El producto "' . $producto->__toString() . '" tiene un stock maximo de ' . $producto->cantidadDisponible . ' unidades');

					self::$error = $producto->__toString();
					throw new Delivery_Model_Exception( Delivery_Model_Exception::ORDER_CREATION_STOCK );
				}
				
				$stoks[$producto->idProducto] = $producto->cantidadDisponible - $producto->cantidad;
				
				$total+= $producto->getPrecioTotal();		
			}
			
			foreach ($promocionesP as $promocion){				
			
				$productos = $mapperP->getByIds( array_keys($promocion->productos) );
				$mapperP->loadCategoria( $productos );
				
				foreach ($productos as $producto){				
				
					$n = $promocion->productos[$producto->idProducto];
					
					if ( $producto->cantidadDisponible < $n || (isset($stoks[$producto->idProducto]) && $stoks[$producto->idProducto] < $n )){
//						throw new Delivery_Model_Exception('El producto "' . $producto->__toString() . '" tiene un stock maximo de ' . $producto->cantidadDisponible . ' unidades');
						
						self::$error = $producto->__toString();
						throw new Delivery_Model_Exception( Delivery_Model_Exception::ORDER_CREATION_STOCK );
					}
					
				}
							
				$total+= $promocion->getPrecioTotal();		
			}
	
			
			if ( isset($zona) && $zona->compraMinima > $total ){
//				throw new Delivery_Model_Exception("Imposible realizar el pedido: la compra minima es de $zona->compraMinima");	
				self::$error = $zona->compraMinima;
				throw new Delivery_Model_Exception( Delivery_Model_Exception::ORDER_CREATION_MINIMUM );
			}
			
			$fechaEntrega = new Zend_Date($fechaEntrega);
			
			$pedido = new Delivery_Model_Pedido(array());
			$pedido->idCliente		= $cliente->idCliente;
			$pedido->idNegocio		= $negocio->idNegocio;
			$pedido->notasCliente	= $notasCliente;
			$pedido->precioFinal	= $total;
			$pedido->costoEnvio		= isset($zona) ? $zona->precio : 0;
			$pedido->estado			= 1;
			$pedido->pagaCon		= $pagaCon;
			$pedido->fechaCreacion	= date("Y:m:d H:i:s");
			$pedido->fechaEntrega	= $fechaEntrega->get( "YYYY-MM-dd" ) . ' ' . $fechaEntrega->get( Zend_Date::TIME_MEDIUM );
			$pedido->fechaCancelacion= $this->_fechaCancelacion($negocio, $fechaEntrega);
				
			if ( $tipo == 'delivery' ){
				$pedido->idDireccionCliente	= $direccion->idDireccionCliente;
			}
			
			$mapperP2->save( $pedido );
			
			$mapperPP = Delivery_Model_Factory::mapper( 'ProductosPedido' );
			
			foreach ($productosP as $producto){	
				$producto->idPedido = $pedido->idPedido;
				$mapperPP->save( $producto, true, true );		
			} 
			
			$mapperPP = Delivery_Model_Factory::mapper( 'PromocionesPedido' );
			
			
			foreach ($promocionesP as $promocion){	
				$promocion->idPedido = $pedido->idPedido;
				$mapperPP->save( $promocion, true, true );	
			} 
			
			$pedido->setNegocio( $negocio );
			$pedido->setCliente( $cliente );
			
			$db->commit();
			
			return $pedido;
		
		} catch (Delivery_Model_Exception $e) {
		
			$db->rollBack();
			throw $e;
		}catch (Zend_Exception $e) {
		
			$db->rollBack();
			throw $e;
		}
			
	}	
	
	
	public function rechazar( $pedido, $fromSystem = false )
	{				
		$db = Zend_Registry::get('db');								
		$db->beginTransaction();
		
		$mapper = Delivery_Model_Factory::mapper('Pedidos');
		$mapper->loadProductos( $pedido );
		$mapper->loadPromociones( $pedido );
		
		
		try {
		
		    if( $fromSystem ){
		        $pedido->cancelar();
		    } else {
		        $pedido->rechazar();
		    }
			
			$mapper->save( $pedido );
			
			$mapper2 = Delivery_Model_Factory::mapper('ProductosPedido');
			
			foreach ($pedido->getProductos() as $producto){	
				$mapper2->save( $producto, true, false);	
			} 
				
			$mapper3 = Delivery_Model_Factory::mapper('PromocionesPedido');
			
			foreach ($pedido->getPromociones() as $promocion){	
				$mapper3->save( $promocion, true, false);
			} 
			
			$db->commit();
			
			
		} catch (Delivery_Model_Exception $e) {
		
			$db->rollBack();
			throw $e;
		}
		catch (Zend_Exception $e) {
		
			$db->rollBack();
			throw $e;
		}
	}
	
    public function cancelar( $pedido )
	{				
		return $this->rechazar( $pedido, true );
	}
	
	
	
	protected function _fechaCancelacion( $negocio, $fechaEntrega )
	{
		$now = Zend_Date::now();
		
		if( $negocio->estaOnline() ) {
			
			$fechaCancelacion = clone $now;
			
			$fechaCancelacion->addMinute( self::MINUTES);
			
		} else {
		
			$fechaCancelacion = clone $fechaEntrega;
			
			$fechaCancelacion->subMinute( current(explode("-", $negocio->tiempoEntrega)));
			
			// si la diferencia entre la fcha de cancelacion y ahora es menor de 10 minutos, entonces le agrego la diferencia.
			
			$lastDay = clone $fechaCancelacion;
			$diff = $lastDay->sub( $now )->toValue();
			$diff = (int) ceil($diff/60) +1;
			
			if ( $diff < self::MINUTES ){
				
				$fechaCancelacion->addMinute( self::MINUTES - $diff);
			}
		}
		
		return $fechaCancelacion->get( "YYYY-MM-dd" ) . ' ' . $fechaCancelacion->get( Zend_Date::TIME_MEDIUM );
	}
	
	protected function _isValidTime( $horariosWeek, $fechaEntrega )
	{
	    foreach( $horariosWeek as $date=>$horarios ){
	        
	        if(isset( $horarios[$fechaEntrega] )){
	            return true;
	        }
	    }
	    return false;
	}
	
}